package store

import (
	"fmt"
	"github.com/google/uuid"
	"guard/internal/app/oauth/models"
	"guard/internal/conf"
	"guard/internal/tool"
	"time"
)

/**
1.缩略掉err判断，某些地方没有缩略，因为设计数组操作，结构体赋值操作函数，都缩略了
2.除数组，切片操作，其它的err直接返回给service层处理
*/

const AccessTokenType = "Bearer"

func (s *oauthStoreImpl) SelClient(clientIdReq string) (registerId, clientId, clientName, clientSecret, grantTypes, redirectUri, scope string, codeExp, tokenExp, rTokenExp int64, err error) {
	var oauthClient models.OAuth2RegisteredClient
	err = s.db.Raw("select * from oauth2_registered_client where client_id = ?", clientIdReq).Scan(&oauthClient).Error
	registerId = oauthClient.Id
	clientId = oauthClient.ClientId
	clientName = oauthClient.ClientName
	clientSecret = oauthClient.ClientSecret
	grantTypes = oauthClient.AuthorizationGrantTypes
	redirectUri = oauthClient.RedirectUris
	scope = oauthClient.Scopes
	codeExp = oauthClient.AuthorizationCodeExpires
	tokenExp = oauthClient.AccessTokenExpires
	rTokenExp = oauthClient.RefreshTokenExpires
	return
}

func (s *oauthStoreImpl) SelAuthorizationInfo(stateReq, username string) (aId, attributes string, err error) {
	var oauthInfo models.OAuth2Authorization
	err = s.db.Raw("select * from oauth2_authorization where state = ? and principal_name = ?", stateReq, username).Scan(&oauthInfo).Error
	return oauthInfo.Id, oauthInfo.Attribute, err
}

func (s *oauthStoreImpl) SaveAuthorization(registerId, userName, grantTypes, attributes, state, codeChallenge, codeChallengeMethod string) error {
	// 保存第一次的授权信息
	var aInfo models.OAuth2Authorization
	aInfo.Id = uuid.New().String()
	aInfo.PrincipalName = userName
	aInfo.RegisteredClientId = registerId
	// att信息
	aInfo.Attribute = attributes
	aInfo.AuthorizationGrantTypes = grantTypes
	aInfo.State = state
	aInfo.CodeChallengeValue = codeChallenge
	aInfo.CodeChallengeMethod = codeChallengeMethod
	return s.db.Save(&aInfo).Error
}

func (s *oauthStoreImpl) SaveAuthentication(aid, code, scope string, codeExp int64) error {
	_, expTime := tool.CalculateExpiresTime(codeExp)
	// 更新
	return s.db.Exec("update oauth2_authorization set state=null,authorization_code_value=?,authorization_code_expires_at=?,access_token_scopes=? where id=?", code, expTime, scope, aid).Error
}

func (s *oauthStoreImpl) SelAuthentication(code string) (aid, username, att, codeChallenge, scope string, codeExp int64, err error) {
	// 查询授权信息
	var authInfo models.OAuth2Authorization
	err = s.db.Raw("select * from oauth2_authorization where authorization_code_value = ?", code).Scan(&authInfo).Error
	aid = authInfo.Id
	username = authInfo.PrincipalName
	att = authInfo.Attribute
	codeChallenge = authInfo.CodeChallengeValue
	scope = authInfo.AccessTokenScopes
	codeExp = authInfo.AuthorizationCodeExpiresAt
	return
}

func (s *oauthStoreImpl) SaveToken(aId, token, refreshToken, openId, scope string, tokenExp, rTokenExp int64) error {
	nowTime := time.Now().Unix()
	tokenSql := "update oauth2_authorization set authorization_code_expires_at = ?,access_token_value=?,access_token_expires_at=?,access_token_type=?,access_token_scopes=?,refresh_token_value=?,refresh_token_expires_at=?,oidc_id_token_value=? where id=?"
	return s.db.Exec(tokenSql, nowTime, token, tokenExp, AccessTokenType, scope, refreshToken, rTokenExp, openId, aId).Error
}

func (s *oauthStoreImpl) SelToken(token string) (aId, clientId, username, refreshToken string, err error) {
	var authI models.OAuth2Authorization
	err = s.db.Raw("select * from oauth2_authorization where access_token_value = ?", token).Scan(&authI).Error
	aId = authI.Id
	clientId = authI.RegisteredClientId
	username = authI.PrincipalName
	refreshToken = authI.RefreshTokenValue
	return
}

func (s *oauthStoreImpl) SelRefreshToken(refreshToken string) (aId, att, username, scope, openId string, rTokenExp int64, err error) {
	var authI models.OAuth2Authorization
	err = s.db.Raw("select * from oauth2_authorization where refresh_token_value = ?", refreshToken).Scan(&authI).Error
	aId = authI.Id
	att = authI.Attribute
	username = authI.PrincipalName
	scope = authI.AccessTokenScopes
	openId = authI.OidcIdTokenValue
	rTokenExp = authI.RefreshTokenExpiresAt
	return
}

func (s *oauthStoreImpl) DelAuthentication(aid string) error {
	return s.db.Exec("delete from oauth2_authorization where id = ?", aid).Error
}

func (s *oauthStoreImpl) SelScopeTag(tag string) (id int, name, tagDb, permission, remarks string, err error) {
	var scopeObj models.OAuth2Scope
	err = s.db.Raw("select * from oauth2_scope where tag = ?", tag).Scan(&scopeObj).Error
	id = scopeObj.Id
	name = scopeObj.Name
	tagDb = scopeObj.Tag
	permission = scopeObj.Permission
	remarks = scopeObj.Remarks
	return
}

// SelConsentInfo 新增的功能
func (s *oauthStoreImpl) SelConsentInfo(clientId, username string) (scope string, err error) {
	var consent models.OAuth2AuthorizationConsent
	err = s.db.Raw("select * from oauth2_authorization_consent where registered_client_id = ? and principal_name = ?", clientId, username).Scan(&consent).Error
	return consent.Authorities, err
}

// SaveConsent 保存一下功能
func (s *oauthStoreImpl) SaveConsent(clientId, username, scope string) (err error) {
	selConsentInfo, err := s.SelConsentInfo(clientId, username)
	if len(selConsentInfo) <= 0 {
		return nil
	}
	var consent models.OAuth2AuthorizationConsent
	consent.RegisteredClientId = clientId
	consent.PrincipalName = username
	consent.Authorities = scope
	err = s.db.Save(consent).Error
	return err
}

// SelUserScopeTag 查询用户是否有范围
func (s *oauthStoreImpl) SelUserScopeTag(username string) (scope string, err error) {
	userScopeTagSql := fmt.Sprintf("select user_scope_tag from %v where %v = ?", conf.Conf.User.UserTableScope, conf.Conf.User.UserTableField)
	err = s.db.Raw(userScopeTagSql, username).Row().Scan(&scope)
	return
}
